package com.tengju.bff.interfaces.manage.crm.report;

import com.tengju.bff.interfaces.covercharge.util.ExcelExportUtil;
import com.tengju.bff.interfaces.manage.common.facade.CommonManageFacade;
import com.tengju.bff.interfaces.manage.crm.dealer.facade.ReportDealerInfoFacade;
import com.tengju.bff.interfaces.manage.crm.report.facade.SecMonthReportFacade;
import com.tengju.bff.interfaces.shared.*;
import com.tengju.bff.interfaces.shared.render.ChartVO;
import com.tengju.bff.interfaces.shared.render.PieVO;
import com.tengju.bff.interfaces.shared.servlet.ManageEntrance;
import com.tengju.bff.interfaces.shared.servlet.ServletContextUtil;
import com.tengju.support.domain.annotation.BizLog;
import com.tengju.support.domain.annotation.BizLogSysName;
import com.tengju.user.application.shared.ApplicationException;
import com.tengju.user.application.user.UserDocumentService;
import com.tengju.user.domain.model.doc.UserDocument;
import com.tengju.user.domain.model.user.StarLevelEnum;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.shared.DomainException;
import com.tengju.user.domain.shared.ResultCodeEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.tengju.user.domain.shared.ResultCodeEnum.SYS_EXCEPTION;

/**
 * @author chenhang
 * @Date 2021/7/8
 */
@Validated
@RestController
@Api(tags = "数据月报")
@RequestMapping(value = "manage/crm/monthReport")
@Slf4j
@ManageEntrance
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class SecMonthReportController {

    private final CommonManageFacade commonManageFacade;
    private final SecMonthReportFacade secMonthReportFacade;
    private final UserDocumentService userDocumentService;
    private final ReportDealerInfoFacade reportDealerInfoFacade;

    @ApiOperation(value = "SEC收益统计", notes = "SEC收益统计")
    @RequestMapping(value = "/profitAnalysis", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<List<KVVO>> profitAnalysis(@RequestParam("month") Integer month,
                                                  @RequestParam("idCode") Long idCode) {
        return ApiResponse.newSuccess(secMonthReportFacade.profitAnalysis(idCode, month));
    }

    @ApiOperation(value = "SEC收益统计饼图", notes = "SEC收益统计饼图")
    @RequestMapping(value = "/profitPie", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<PieVO> profitPie(@RequestParam("month") Integer month,
                                        @RequestParam("idCode") Long idCode) {
        return ApiResponse.newSuccess(secMonthReportFacade.profitPie(idCode, month));
    }

    @ApiOperation(value = "SEC收益分布统计", notes = "SEC收益分布统计")
    @RequestMapping(value = "/profitDistributedAnalysis", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<TableVO> profitDistributedAnalysis(@RequestParam("month") Integer month,
                                                          @RequestParam("idCode") Long idCode) {
        return ApiResponse.newSuccess(secMonthReportFacade.profitDistributedAnalysis(idCode, month));
    }

    @ApiOperation(value = "SEC收益分布柱状图", notes = "SEC收益分布柱状图")
    @RequestMapping(value = "/profitDistributedChart", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<ChartVO> profitDistributedChart(@RequestParam("month") Integer month,
                                                       @RequestParam("idCode") Long idCode) {

        return ApiResponse.newSuccess(secMonthReportFacade.profitDistributedChart(idCode, month));
    }

    @ApiOperation(value = "SEC销售分析", notes = "SEC销售分析")
    @RequestMapping(value = "/achievementAnalysis", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<TableVO> achievementAnalysis(@RequestParam("month") Integer month,
                                                    @RequestParam("idCode") Long idCode) {
        return ApiResponse.newSuccess(secMonthReportFacade.achievementAnalysis(idCode, month));
    }

    @ApiOperation(value = "SEC品牌销售分析", notes = "SEC品牌销售分析")
    @RequestMapping(value = "/brandGmvAnalysis", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<TableVO> brandGmvAnalysis(@RequestParam("month") Integer month,
                                                 @RequestParam("idCode") Long idCode) {

        return ApiResponse.newSuccess(secMonthReportFacade.brandGmvAnalysis(idCode, month));
    }

    @ApiOperation(value = "SEC团队地区分析", notes = "SEC团队地区分析")
    @RequestMapping(value = "/teamRegionAnalysis", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<TableVO> teamRegionAnalysis(@RequestParam("month") Integer month,
                                                   @RequestParam("idCode") Long idCode) {

        return ApiResponse.newSuccess(secMonthReportFacade.teamRegionAnalysis(idCode, month));
    }

    @ApiOperation(value = "SEC团队分析", notes = "SEC团队分析")
    @RequestMapping(value = "/teamAnalysis", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<TableVO> teamAnalysis(@RequestParam("month") Integer month,
                                             @RequestParam("idCode") Long idCode) {

        return ApiResponse.newSuccess(secMonthReportFacade.teamAnalysis(idCode, month));
    }

    @ApiOperation(value = "SEC团队饼图", notes = "SEC团队饼图")
    @RequestMapping(value = "/teamAnalysisPie", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<PieVO> teamAnalysisPie(@RequestParam("month") Integer month,
                                              @RequestParam("idCode") Long idCode) {

        return ApiResponse.newSuccess(secMonthReportFacade.teamAnalysisPie(idCode, month));
    }

    @ApiOperation(value = "SEC团队新增用户饼图", notes = "SEC团队新增用户饼图")
    @RequestMapping(value = "/teamNewUserPie", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<PieVO> teamNewUserPie(@RequestParam("month") Integer month,
                                             @RequestParam("idCode") Long idCode) {

        return ApiResponse.newSuccess(secMonthReportFacade.teamNewUserPie(idCode, month));
    }

    @ApiOperation(value = "SEC我的客户列表", notes = "SEC我的客户列表")
    @RequestMapping(value = "/teamUserTable", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<TableVO> teamUserTable(@RequestParam("month") Integer month,
                                              @RequestParam("idCode") Long idCode) {

        return ApiResponse.newSuccess(secMonthReportFacade.teamUserTopTable(idCode, month));
    }

    @ApiOperation(value = "获取月度列表", notes = "获取月度列表")
    @RequestMapping(value = "getMonthList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ApiResponse<List<KVVO>> getMonthList() {
        try {
            return ApiResponse.newSuccess(commonManageFacade.getMonthList(LocalDate.of(2021, 7, 1)));
        } catch (DomainException | ApplicationException e) {
            log.error("获取月度列表失败", e);
            return ApiResponse.newFailure(ResultCodeEnum.BIZ_ERROR.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("获取月度列表异常", e);
            return ApiResponse.newFailure(SYS_EXCEPTION.getCode(), e.getMessage());
        }
    }

    @BizLog(sysName = BizLogSysName.TENGJU_CRM)
    @ApiOperation(value = "月入分析导出", notes = "月入分析导出")
    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public void export(@RequestParam("month") Integer month,
                       @RequestParam("idCode") Long idCode) throws Exception {
        HttpServletRequest request = ServletContextUtil.getRequest();
        HttpServletResponse response = ServletContextUtil.getResponse();
        ExcelExportUtil excel = new ExcelExportUtil(2, "汇总看板", "服务商名单");

        UserDocument userDocument = userDocumentService.findById(new UserIdCode(idCode));
        String starLevel = Optional.ofNullable(userDocument).map(u -> Optional.ofNullable(StarLevelEnum.parseByCode(u.getStarLevel())).map(StarLevelEnum::getShortName).orElse("")).orElse("");
        String name = Optional.ofNullable(userDocument)
                .map(u -> String.format("%s %s(%s)", u.getNickName(), starLevel, idCode))
                .orElse(String.format("(%s)", idCode));

        int size = 2;

        // 收益统计
        List<KVVO> profitAnalysis = secMonthReportFacade.profitAnalysis(idCode, month);
        profitAnalysis.add(0, KVVO.of("SEC", name));
        excel.create(0, 1, size, profitAnalysis);
        size = size + 4;

        // 收益分布
        TableVO profitDistributedAnalysis = secMonthReportFacade.profitDistributedAnalysis(idCode, month);
        excel.create(0, 1, size, profitDistributedAnalysis);
        size = size + Optional.ofNullable(profitDistributedAnalysis.getRecords()).map(List::size).orElse(0) + 3;

        // 销售分析
        TableVO achievementAnalysis = secMonthReportFacade.achievementAnalysis(idCode, month);
        achievementAnalysis.addColumn("amt", ColumnVO.of("current_month_rank", "本月排名", false));
        achievementAnalysis.addColumn("lastYearMonthAmt", ColumnVO.of("last_year_month_amt_ratio", "去年同比", false));
        achievementAnalysis.addColumn("lastMonthAmt", ColumnVO.of("last_month_amt_ratio", "上月环比", false));
        List<Map<String, Object>> records = achievementAnalysis.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            for (Map<String, Object> map : records) {
                RankVO rankDiff = (RankVO) map.get("rankVO");
                String upOrDown = Optional.ofNullable(rankDiff)
                        .map(RankVO::getType)
                        .map(RankDiffType::getUpOrDown)
                        .orElse(null);
                if (upOrDown == null) {
                    map.put("current_month_rank", map.get("rank"));
                } else {
                    map.put("current_month_rank", String.format("%s %s %s", map.get("rank"), upOrDown, rankDiff.getRankDiff()));
                }
            }
        }
        excel.create(0, 1, size, achievementAnalysis);
        size = size + Optional.ofNullable(achievementAnalysis.getRecords()).map(List::size).orElse(0) + 3;

        // 品牌销售TOP10
        TableVO brandGmvAnalysis = secMonthReportFacade.brandGmvAnalysis(idCode, month);
        brandGmvAnalysis.filledRowCol(size, 1);
        excel.fillAndMergeHeader(0, 1, size, brandGmvAnalysis);
        size = size + brandGmvAnalysis.headerDepth() - 1;
        excel.createRecords(0, 1, size, brandGmvAnalysis);
        size = size + Optional.ofNullable(brandGmvAnalysis.getRecords()).map(List::size).orElse(0) + 3;

        // 团队分析
        TableVO teamAnalysis = secMonthReportFacade.teamAnalysis(idCode, month);
        ColumnVO teamAnalysisFirstColumnVO = teamAnalysis.getHeader().get(0);
        teamAnalysisFirstColumnVO.setLabel("团队数据/类型");
        excel.create(0, 1, size, teamAnalysis);
        size = size + Optional.ofNullable(teamAnalysis.getRecords()).map(List::size).orElse(0) + 3;

        // TOP10城市
        TableVO teamRegionAnalysis = secMonthReportFacade.teamRegionAnalysis(idCode, month);
        ColumnVO teamRegionAnalysisFirstColumnVO = teamRegionAnalysis.getHeader().get(0);
        teamRegionAnalysisFirstColumnVO.setLabel("TOP10城市");
        excel.create(0, 1, size, teamRegionAnalysis);
        size = size + Optional.ofNullable(teamRegionAnalysis.getRecords()).map(List::size).orElse(0) + 3;

        // 直属服务商
        TableVO teamUserTable = secMonthReportFacade.teamUserTable(idCode, month);
        excel.create(0, 1, size, teamUserTable);

        // sheet2 服务商名单
        TableVO dominationStarMember = reportDealerInfoFacade.getDominationStarMember(idCode, month);
        excel.create(1, dominationStarMember);

        String fileName = String.format("%s(%s)月度分析_%s.xls", starLevel, idCode, month);
        excel.downloadExcel(request, response, fileName);
    }
}
